/**
 ** perf - Performance metrics
 *
 * The perf module provides functions to measure and display runtime performance metrics.
 */

define('oj/perf', ['oj/element'], function (element) {
    'use strict';
    
    var perf = {
        
        /* Properties */
        meter : undefined,
        ms    : 0,
        fps   : 0,
        
        /* Functions */
        update : function (time) {}
        
    };
    
    
    var perf_d,
        perf_p = (new Date).getTime(),
        perf_u = perf_p + 1000,
        perf_f = 0,
        perf_ms_layer,
        perf_fps_layer,
        perf_ms_lbl,
        perf_fps_lbl,
        perf_ms = [],
        perf_fps = [],
        perf_tmp;
    
    
    perf.meter = element.create(document.body, 'div', 'perf_meter', [
        perf_fps_layer = element.create('div', 'perf_layer'),
        perf_ms_layer = element.create('div', 'perf_layer', [
            perf_fps_lbl = element.create('div', 'perf_fps_lbl'),
            perf_ms_lbl = element.create('div', 'perf_ms_lbl')
        ])
    ]);
    
    
    perf.update = function (time) {
        /**
         *> perf.update(time)
         *
         * Updates performance metrics.
         */
        
        perf.ms = time - perf_p;
        
        if (perf_ms.length > 0 && (perf_ms_layer.offsetLeft - perf_ms[0].offsetWidth) < 0) {
            perf_tmp = perf_ms.shift();
            perf_ms_layer.removeChild(perf_tmp);
        } else {
            perf_tmp = element.create('div', 'perf_ms');
        }
        
        perf_ms.push(perf_tmp);
        perf_ms_layer.appendChild(perf_tmp);
        perf_p = ~~((perf.ms / 250) * perf.meter.offsetHeight);
        
        if (perf_p > perf.meter.offsetHeight) {
            perf_p = perf.meter.offsetHeight;
        } else if (perf_p < 0) {
            perf_p = 0;
        }
        
        perf_tmp.style.marginTop = (perf.meter.offsetHeight - perf_p) + 'px';
        perf_tmp.style.height = perf_p + 'px';
        perf_ms_lbl.innerHTML = perf.ms;
        perf_ms_lbl.style.bottom = perf_tmp.style.height;
        
        perf_f++;
        
        if (time > perf_u) {
            perf.fps = Math.round((perf_f*1000)/(time-(perf_u-1000)));
            
            if (perf_fps.length > 0 && (perf_fps_layer.offsetLeft - perf_fps[0].offsetWidth) < 0) {
                perf_tmp = perf_fps.shift();
                perf_fps_layer.removeChild(perf_tmp);
            } else {
                perf_tmp = element.create('div', 'perf_fps');
            }
            
            perf_fps.push(perf_tmp);
            perf_fps_layer.appendChild(perf_tmp);
            
            perf_f = ~~((perf_p / 80) * perf.meter.offsetHeight);
            
            if (perf_f > perf.meter.offsetHeight) {
                perf_f = perf.meter.offsetHeight;
            } else if (perf_f < 0) {
                perf_f = 0;
            }
            
            perf_tmp.style.marginTop = (perf.meter.offsetHeight - perf_f) + 'px';
            perf_tmp.style.height = perf_f + 'px';
            perf_fps_lbl.innerHTML = perf.fps;
            perf_fps_lbl.style.bottom = perf_tmp.style.height;
            
            perf_u = time + 1000;
            perf_f = 0;
        }
        
        perf_p = time;
    }
    
    
    element.create(document.head, 'style', {'type': 'text/css'}, [
        '.perf_meter{position:absolute;width:100px;height:50px;display:none;overflow:hidden}',
        '.perf_layer{position:absolute;right:0;bottom:0;overflow:hide}',
        '.perf_fps_lbl{position:absolute;right:3px;font-size:7pt;font-weight:bold;color:#F6993C}',
        '.perf_ms_lbl{position:absolute;right:3px;font-size:7pt;font-weight:bold;color:#F6993C}',
        '.perf_ms{display:inline;float:left;background:#EEFFCC;width:1px}',
        '.perf_fps{display:inline;float:left;background:#D85A28;width:5px}'
    ]);
    
    
    
    return perf;
    
});
